package cn.sylinx.horm.config;

import java.sql.Connection;

import cn.sylinx.horm.model.strategy.Strategy;
import cn.sylinx.horm.util.GLog;
import cn.sylinx.horm.util.StrKit;

/**
 * 配置相关
 *
 * @author johnhan
 */
public class OrmConfig implements Cloneable {

    public static final String DEFAULT_MAPPER_POST_FIX = ".mapper.xml";
    public static final String DEFAULT_SQL_POST_FIX = ".sql";
    public static final String DEFAULT_SQL_SCAN_DIR = "horm";

    // 慢SQL 100毫秒探测1次
    public static final long DEFAULT_STAT_INTERNAL = 100L;
    // 慢SQL 默认阈值3秒
    public static final long DEFAULT_STAT_THRESHOLD = 3000L;

    // 是否启用调试
    private boolean debug = false;
    // 缓存key使用md5加密
    private boolean cacheKeyMd5 = true;

    // 是否大小写敏感，默认不敏感
    private boolean caseSensitive = false;
    // 乐观锁是否启用
    private boolean optimisticLockEnable = false;
    // jdbc 事务隔离级别，普通java项目中可设置
    private int transactionIsolation = Connection.TRANSACTION_READ_COMMITTED;
    // 是否开启SQL统计
    private boolean sqlStatOpen = false;
    // sql执行超时时间，默认3秒
    private long sqlExecuteTimeThreshold = 3000L;
    // sql资源 匹配后缀
    private String sqlPostfix = DEFAULT_SQL_POST_FIX;
    // command 扫描包（Springboot环境下无需手动指定）
    private String commandScanPackage;
    // mapper 扫描包（Springboot环境下无需手动指定）
    private String mapperScanPackage;
    // mapper 匹配后缀
    private String mapperPostfix = DEFAULT_MAPPER_POST_FIX;
    // 模型映射策略，underline ｜ attr （下划线、属性一致）
    private String modelMapStrategy = Strategy.STRATEGY_UNDERLINE;
    // sql解析类型，默认system
    private String parseSqlType = ParseSqlType.SYSTEM.getType();
    // 解析sql资源是否区分数据库类型，默认否
    private boolean parseSqlPathDbtype = false;
    // 启动时加载对有Model注解的实体到缓存
    private boolean cacheModelOnStart = false;
    // 缓存Model扫描包（Springboot环境下无需设置）
    private String modelScanPackage;
    // SqlClient拦截器
    private String interceptorClass;
    // command拦截器
    private String commandInterceptorClass;
    // mapper拦截器
    private String mapperInterceptorClass;
    // 打印sql用时
    private boolean printSqlUseTime = false;

    public boolean isDebug() {
        return debug;
    }

    public OrmConfig setDebug(boolean debug) {
        this.debug = debug;
        return this;
    }

    public String getSqlPostfix() {
        return sqlPostfix;
    }

    public OrmConfig setSqlPostfix(String sqlPostfix) {

        if (StrKit.isBlank(sqlPostfix)) {
            sqlPostfix = DEFAULT_SQL_POST_FIX;
        }
        this.sqlPostfix = sqlPostfix;
        return this;
    }

    public String getCommandScanPackage() {
        return commandScanPackage;
    }

    public OrmConfig setCommandScanPackage(String commandScanPackage) {
        this.commandScanPackage = commandScanPackage;
        return this;
    }

    public String getMapperScanPackage() {
        return mapperScanPackage;
    }

    public OrmConfig setMapperScanPackage(String mapperScanPackage) {
        this.mapperScanPackage = mapperScanPackage;
        return this;
    }

    public String getModelMapStrategy() {
        return modelMapStrategy;
    }

    public OrmConfig setModelMapStrategy(String modelMapStrategy) {
        this.modelMapStrategy = modelMapStrategy;
        return this;
    }

    public boolean isParseSqlPathDbtype() {
        return parseSqlPathDbtype;
    }

    public OrmConfig setParseSqlPathDbtype(boolean parseSqlPathDbtype) {
        this.parseSqlPathDbtype = parseSqlPathDbtype;
        return this;
    }

    public boolean isCacheModelOnStart() {
        return cacheModelOnStart;
    }

    public OrmConfig setCacheModelOnStart(boolean cacheModelOnStart) {
        this.cacheModelOnStart = cacheModelOnStart;
        return this;
    }

    public String getModelScanPackage() {
        return modelScanPackage;
    }

    public OrmConfig setModelScanPackage(String modelScanPackage) {
        this.modelScanPackage = modelScanPackage;
        return this;
    }

    public String getMapperPostfix() {
        return mapperPostfix;
    }

    public OrmConfig setMapperPostfix(String mapperPostfix) {
        if (StrKit.isBlank(mapperPostfix)) {
            mapperPostfix = DEFAULT_MAPPER_POST_FIX;
        }
        this.mapperPostfix = mapperPostfix;
        return this;
    }

    public String getInterceptorClass() {
        return interceptorClass;
    }

    public void setInterceptorClass(String interceptorClass) {
        this.interceptorClass = interceptorClass;
    }

    public String getCommandInterceptorClass() {
        return commandInterceptorClass;
    }

    public OrmConfig setCommandInterceptorClass(String commandInterceptorClass) {
        this.commandInterceptorClass = commandInterceptorClass;
        return this;
    }

    public String getMapperInterceptorClass() {
        return mapperInterceptorClass;
    }

    public OrmConfig setMapperInterceptorClass(String mapperInterceptorClass) {
        this.mapperInterceptorClass = mapperInterceptorClass;
        return this;
    }

    public boolean isCaseSensitive() {
        return caseSensitive;
    }

    public OrmConfig setCaseSensitive(boolean caseSensitive) {
        this.caseSensitive = caseSensitive;
        return this;
    }

    public boolean isOptimisticLockEnable() {
        return optimisticLockEnable;
    }

    public OrmConfig setOptimisticLockEnable(boolean optimisticLockEnable) {
        this.optimisticLockEnable = optimisticLockEnable;
        return this;
    }

    public int getTransactionIsolation() {
        return transactionIsolation;
    }

    public OrmConfig setTransactionIsolation(int transactionIsolation) {
        this.transactionIsolation = transactionIsolation;
        return this;
    }

    public boolean isSqlStatOpen() {
        return sqlStatOpen;
    }

    public OrmConfig setSqlStatOpen(boolean sqlStatOpen) {
        this.sqlStatOpen = sqlStatOpen;
        return this;
    }

    public long getSqlExecuteTimeThreshold() {
        return sqlExecuteTimeThreshold;
    }

    public OrmConfig setSqlExecuteTimeThreshold(long sqlExecuteTimeThreshold) {
        this.sqlExecuteTimeThreshold = sqlExecuteTimeThreshold;
        return this;
    }

    public String getParseSqlType() {
        return parseSqlType;
    }

    public OrmConfig setParseSqlType(String parseSqlType) {
        this.parseSqlType = parseSqlType;
        return this;
    }

    public boolean isCacheKeyMd5() {
        return cacheKeyMd5;
    }

    public OrmConfig setCacheKeyMd5(boolean cacheKeyMd5) {
        this.cacheKeyMd5 = cacheKeyMd5;
        return this;
    }

    public boolean isPrintSqlUseTime() {
        return printSqlUseTime;
    }

    public OrmConfig setPrintSqlUseTime(boolean printSqlUseTime) {
        this.printSqlUseTime = printSqlUseTime;
        return this;
    }

    @Override
    public Object clone() {
        OrmConfig clone = null;
        try {
            clone = (OrmConfig) super.clone();
        } catch (CloneNotSupportedException e) {
            GLog.error("clone error", e);
            return createCloneObject();
        }
        return clone;
    }

    private Object createCloneObject() {
        OrmConfig c = new OrmConfig();
        c.setCacheModelOnStart(cacheModelOnStart);
        c.setCaseSensitive(caseSensitive);
        c.setCommandInterceptorClass(commandInterceptorClass);
        c.setCommandScanPackage(commandScanPackage);
        c.setDebug(debug);
        c.setInterceptorClass(commandInterceptorClass);
        c.setMapperInterceptorClass(mapperInterceptorClass);
        c.setMapperPostfix(mapperPostfix);
        c.setMapperScanPackage(mapperScanPackage);
        c.setTransactionIsolation(transactionIsolation);
        c.setSqlPostfix(sqlPostfix);
        c.setSqlExecuteTimeThreshold(sqlExecuteTimeThreshold);
        c.setParseSqlPathDbtype(parseSqlPathDbtype);
        c.setOptimisticLockEnable(optimisticLockEnable);
        c.setModelScanPackage(modelScanPackage);
        c.setModelMapStrategy(modelMapStrategy);
        c.setSqlStatOpen(sqlStatOpen);
        c.setParseSqlType(parseSqlType);
        c.setCacheKeyMd5(cacheKeyMd5);
        c.setPrintSqlUseTime(printSqlUseTime);
        return c;
    }

    @Override
    public String toString() {
        return "OrmConfig{" +
                "debug=" + debug +
                ", cacheKeyMd5=" + cacheKeyMd5 +
                ", caseSensitive=" + caseSensitive +
                ", optimisticLockEnable=" + optimisticLockEnable +
                ", transactionIsolation=" + transactionIsolation +
                ", sqlStatOpen=" + sqlStatOpen +
                ", sqlExecuteTimeThreshold=" + sqlExecuteTimeThreshold +
                ", sqlPostfix='" + sqlPostfix + '\'' +
                ", commandScanPackage='" + commandScanPackage + '\'' +
                ", mapperScanPackage='" + mapperScanPackage + '\'' +
                ", mapperPostfix='" + mapperPostfix + '\'' +
                ", modelMapStrategy='" + modelMapStrategy + '\'' +
                ", parseSqlType='" + parseSqlType + '\'' +
                ", parseSqlPathDbtype=" + parseSqlPathDbtype +
                ", cacheModelOnStart=" + cacheModelOnStart +
                ", modelScanPackage='" + modelScanPackage + '\'' +
                ", interceptorClass='" + interceptorClass + '\'' +
                ", commandInterceptorClass='" + commandInterceptorClass + '\'' +
                ", mapperInterceptorClass='" + mapperInterceptorClass + '\'' +
                ", printSqlUseTime=" + printSqlUseTime +
                '}';
    }
}
